<?php
defined('_JEXEC') or die('Restricted access');
require_once(JPATH_COMPONENT.DS.'data'.DS.'implJoomla'.DS.'JDAOFactory.php');

class FTConnection{
	private static $instance;
	private $_token = null;
	private $_ft = null;
	private $_ftUser = null;
	
	public static function getInstance() 
	    {
	        if (!isset(self::$instance)) {
	            $c = __CLASS__;
	            self::$instance = new $c;
	        }
	        return self::$instance;
	}
	
	private function __construct(){
		$daoUser=JDAOFactory::getInstance()->getDAOFTUser();
		$this->_ftUser=$daoUser->getFTUser();
		// The GoogleClientLogin function will provide 
		// the token, given a Google Account email address, password, and service 
		// (in this case, fusiontables)
		$this->_token = $this->googleClientLogin($this->_ftUser->getEmail(), $this->_ftUser->getPasswd(), "fusiontables");
		$this->_ft = new FusionTable($this->_token);
	}
	
	public function query($query){
		return $this->_ft->query($query);
	}
	
	private function googleClientLogin($username, $password, $service) {
		$data = array ('accountType' => 'GOOGLE', 'Email' => $username, 'Passwd' => $password, 'service' => $service );
		
		$ch = curl_init ();
		curl_setopt ( $ch, CURLOPT_URL, "https://www.google.com/accounts/ClientLogin" );
		curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
		curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );
		curl_setopt ( $ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY );
		curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false );
		curl_setopt ( $ch, CURLOPT_POST, true );
		curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
		$output = curl_exec ( $ch );
		$info = curl_getinfo ( $ch, CURLINFO_HTTP_CODE );
		curl_close ( $ch );
		
		$auth = '';
		if ($info == 200) {
			preg_match ( '/Auth=(.*)/', $output, $matches );
			if (isset ( $matches [1] )) {
				$auth = $matches [1];
			}
		}
		return $auth;
	} 
} 


class FusionTable {
	var $token;
	function FusionTable($token) {
		if (! $token) {
			throw new Exception ( "You must provide a token when creating a new FusionTable." );
		}
		$this->token = $token;
	}
	function query($query) {
		if (! $query) {
			throw new Exception ( "query method requires a query." );
		}
		// Check to see if we have a query that will retrieve data 
		if (preg_match ( "/^select|^show tables|^describe/i", $query )) {
			$request_url = "http://tables.googlelabs.com/api/query?sql=" . urlencode ( $query );
			$c = curl_init ( $request_url );
			curl_setopt ( $c, CURLOPT_HTTPHEADER, array ("Authorization: GoogleLogin auth=" . $this->token ) );
			curl_setopt ( $c, CURLOPT_RETURNTRANSFER, true );
			// Place the lines of the output into an array 
			$results = preg_split ( "/\n/", curl_exec ( $c ));
			// If we got an error, raise it 
			if (curl_getinfo ( $c, CURLINFO_HTTP_CODE ) != 200) {
				return $this->output_error ( $results );
			}
			// Drop the last (empty) array value 
			array_pop ( $results );
			// Parse the output 
			return $this->parse_output ( $results );
		} // Otherwise we are going to be updating the table, so we need to the POST method 
		else if (preg_match ( "/^update|^delete|^insert/i", $query )) {
			// Set up the cURL 
			$body = "sql=" . urlencode ( $query );
			$c = curl_init ( "http://tables.googlelabs.com/api/query" );
			curl_setopt ( $c, CURLOPT_POST, true );
			curl_setopt ( $c, CURLOPT_RETURNTRANSFER, true );
			curl_setopt ( $c, CURLOPT_HTTPHEADER, array ("Content-length: " . strlen ( $body ), "Content-type: application/x-www-form-urlencoded", "Authorization: GoogleLogin auth=" . $this->token . " " ) );
			curl_setopt ( $c, CURLOPT_POSTFIELDS, $body );
			// Place the lines of the output into an array 
			$results = preg_split ( "/\n/", curl_exec ( $c ) );
			// If we got an error, raise it 
			if (curl_getinfo ( $c, CURLINFO_HTTP_CODE ) != 200) {
				return $this->output_error ( $results );
			}
			// Drop the last (empty) array value 
			//array_pop($results); 
			//return $this->parse_output($results); 
			return $results [1];
		} else {
			throw new Exception ( "Unknown SQL query submitted." );
		}
	}
	private function parse_output($results) {
		$headers = false;
		$output = array ();
		foreach ( $results as $row ) {
			// Get the headers 
			if (! $headers) {
				$headers = $this->parse_row ( $row );
			} else {
				// Create a new row for the array 
				$newrow = array ();
				$values = $this->parse_row ( $row );
				// Build an associative array, using the headers for the association 
				foreach ( $headers as $index => $header ) {
					//print_r("header: ".$header." index: ".$index." value: ".$values[$index]."</br>" );
					$newrow [$header] = $values [$index];
				}
				// Add the new array to the output array 
				array_push ( $output, $newrow );
			}
		}
		// Return the output 
		return $output;
	}
	
//	function str_getcsv($input, $delimiter = ',', $enclosure = '"', $escape = null, $eol = null) {
//		$temp = fopen ( "php://memory", "rw" );
//		fwrite ( $temp, $input );
//		fseek ( $temp, 0 );
//		$r = fgetcsv ( $temp, 4096, $delimiter, $enclosure );
//		fclose ( $temp );
//		return $r;
//	}
	
	private function parse_row($row) {
		// Split the comma delimted row 
		//print_r($row."<br/>");
		$cells = str_getcsv ( $row, ',', '"' );
		return $cells;
	}
	private function output_error($err) {
		$err = implode ( "", $err );
		// Remove everything outside of the H1 tag 
		$err = preg_replace ( "/[\s\S]*<H1>|<\/H1>[\s\S]*/i", "", $err );
		// Return the error 
		return $err;
		// Eventually we'll just throw the error rather than return the error output 
		throw new Exception ( $err );
	}
} 

?>